/**
 * Copyright (c) 2010 Werner Dittmann
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.

 */

#ifndef SKEINAPI_H
#define SKEINAPI_H

/**
 * @file skein_api.h
 * @brief A Skein API and its functions.
 * @{
 *
 * This API and the functions that implement this API simplify the usage
 * of Skein. The design and the way to use the functions follow the openSSL
 * design but at the same time take care of some Skein specific behaviour
 * and possibilities.
 *
 * The functions enable applications to create a normal Skein hashes and
 * message authentication codes (MAC).
 *
 * Using these functions is simple and straight forward:
 *
 * @code
 *
 * #include "skein_api.h"
 *
 * ...
 * struct skein_ctx ctx;             // a Skein hash or MAC context
 *
 * // prepare context, here for a Skein with a state size of 512 bits.
 * skein_ctx_prepare(&ctx, SKEIN_512);
 *
 * // Initialize the context to set the requested hash length in bits
 * // here request a output hash size of 31 bits (Skein supports variable
 * // output sizes even very strange sizes)
 * skein_init(&ctx, 31);
 *
 * // Now update Skein with any number of message bits. A function that
 * // takes a number of bytes is also available.
 * skein_update_bits(&ctx, message, msg_length);
 *
 * // Now get the result of the Skein hash. The output buffer must be
 * // large enough to hold the request number of output bits. The application
 * // may now extract the bits.
 * skein_final(&ctx, result);
 * ...
 * @endcode
 *
 * An application may use @c skein_reset to reset a Skein context and use
 * it for creation of another hash with the same Skein state size and output
 * bit length. In this case the API implementation restores some internal
 * internal state data and saves a full Skein initialization round.
 *
 * To create a MAC the application just uses @c skein_mac_init instead of
 * @c skein_init. All other functions calls remain the same.
 *
 */

#include <linux/types.h>
#include "skein_base.h"

/**
 * Which Skein size to use
 */
enum skein_size {
	SKEIN_256 = 256,     /*!< Skein with 256 bit state */
	SKEIN_512 = 512,     /*!< Skein with 512 bit state */
	SKEIN_1024 = 1024    /*!< Skein with 1024 bit state */
};

/**
 * Context for Skein.
 *
 * This structure was setup with some know-how of the internal
 * Skein structures, in particular ordering of header and size dependent
 * variables. If Skein implementation changes this, then adapt these
 * structures as well.
 */
struct skein_ctx {
	u64 skein_size;
	u64 x_save[SKEIN_MAX_STATE_WORDS];   /* save area for state variables */
	union {
		struct skein_ctx_hdr h;
		struct skein_256_ctx s256;
		struct skein_512_ctx s512;
		struct skein_1024_ctx s1024;
	} m;
};

/**
 * Prepare a Skein context.
 *
 * An application must call this function before it can use the Skein
 * context. The functions clears memory and initializes size dependent
 * variables.
 *
 * @param ctx
 *     Pointer to a Skein context.
 * @param size
 *     Which Skein size to use.
 * @return
 *     SKEIN_SUCCESS of SKEIN_FAIL
 */
int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size);

/**
 * Initialize a Skein context.
 *
 * Initializes the context with this data and saves the resulting Skein
 * state variables for further use.
 *
 * @param ctx
 *     Pointer to a Skein context.
 * @param hash_bit_len
 *     Number of MAC hash bits to compute
 * @return
 *     SKEIN_SUCCESS of SKEIN_FAIL
 * @see skein_reset
 */
int skein_init(struct skein_ctx *ctx, size_t hash_bit_len);

/**
 * Resets a Skein context for further use.
 *
 * Restores the saved chaining variables to reset the Skein context.
 * Thus applications can reuse the same setup to  process several
 * messages. This saves a complete Skein initialization cycle.
 *
 * @param ctx
 *     Pointer to a pre-initialized Skein MAC context
 */
void skein_reset(struct skein_ctx *ctx);

/**
 * Initializes a Skein context for MAC usage.
 *
 * Initializes the context with this data and saves the resulting Skein
 * state variables for further use.
 *
 * Applications call the normal Skein functions to update the MAC and
 * get the final result.
 *
 * @param ctx
 *     Pointer to an empty or preinitialized Skein MAC context
 * @param key
 *     Pointer to key bytes or NULL
 * @param key_len
 *     Length of the key in bytes or zero
 * @param hash_bit_len
 *     Number of MAC hash bits to compute
 * @return
 *     SKEIN_SUCCESS of SKEIN_FAIL
 */
int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
		   size_t hash_bit_len);

/**
 * Update Skein with the next part of the message.
 *
 * @param ctx
 *     Pointer to initialized Skein context
 * @param msg
 *     Pointer to the message.
 * @param msg_byte_cnt
 *     Length of the message in @b bytes
 * @return
 *     Success or error code.
 */
int skein_update(struct skein_ctx *ctx, const u8 *msg,
		 size_t msg_byte_cnt);

/**
 * Update the hash with a message bit string.
 *
 * Skein can handle data not only as bytes but also as bit strings of
 * arbitrary length (up to its maximum design size).
 *
 * @param ctx
 *     Pointer to initialized Skein context
 * @param msg
 *     Pointer to the message.
 * @param msg_bit_cnt
 *     Length of the message in @b bits.
 */
int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
		      size_t msg_bit_cnt);

/**
 * Finalize Skein and return the hash.
 *
 * Before an application can reuse a Skein setup the application must
 * reset the Skein context.
 *
 * @param ctx
 *     Pointer to initialized Skein context
 * @param hash
 *     Pointer to buffer that receives the hash. The buffer must be large
 *     enough to store @c hash_bit_len bits.
 * @return
 *     Success or error code.
 * @see skein_reset
 */
int skein_final(struct skein_ctx *ctx, u8 *hash);

/**
 * @}
 */
#endif
